package com.techyuan.algorithm.leetcode;

import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * Created by tianjuntao on 2017/1/4.
 */
public class Tuzi {
    final static ConcurrentLinkedQueue<MoveEvent> moveEventQueue = new ConcurrentLinkedQueue<MoveEvent>();
    final static ConcurrentLinkedQueue<FightEvent> fightEventQueue = new ConcurrentLinkedQueue<FightEvent>();
    static List<FightMoveControl> fightList = null;

    public static void main(String[] args) {
        fightList = new ArrayList<FightMoveControl>();
        fightList.add(new ShanTu(228, "山兔"));
        fightList.add(new ShanTu(224, "镰鼬"));
        fightList.add(new FightMoveControl(125D, "神乐"));
        fightList.add(new FightMoveControl(100D, "狗粮"));
        fightList.add(new FightMoveControl(99D, "犬神"));
//        fightList.add(new FightMoveControl(142D, "怪物3"));

        init();
        int fightCount = 0;
        while (fightCount < 5) {
            GameEvent event = fightEventQueue.poll();
            if (event == null) {
                event = moveEventQueue.poll();
            } else {
                fightCount++;
            }
            if (event == null)
                break;
            event.trigger();
        }
    }

    public static void init() {
        fightEventQueue.clear();
        Collections.sort(fightList, new Comparator<FightMoveControl>() {
            public int compare(FightMoveControl o1, FightMoveControl o2) {
                if (o1.unitSpeed > o2.unitSpeed)
                    return -1;
                return 1;
            }
        });

        for (int i = 0; i < fightList.size(); i++) {
            if (i == 0) {
                fightList.get(i).pos = FightMoveControl.barLen-0.001;
                continue;
            }
            if (i == fightList.size() - 1) {
                fightList.get(i).pos = 0;
                continue;
            }
            double min = fightList.get(fightList.size() - 1).unitSpeed;
            double max = fightList.get(0).unitSpeed;
            fightList.get(i).pos = ((fightList.get(i).unitSpeed - min) / (max -min)) * (FightMoveControl.barLen-0.001);
        }

        for (FightMoveControl fight : fightList) {
            moveEventQueue.add(new MoveEvent(fight, fightList));
        }
    }

    public static class FightMoveControl {
        final static double speedUnit = 1000;
        final static int barLen = 100;
        double unitSpeed;
        double pos;

        String name;

        public FightMoveControl(double speed, String name) {
            this.unitSpeed = speed / speedUnit;
            this.pos = 0;
            this.name = name;
        }

        public void buff() {
        }

        public void deBuff() {
        }

        public Double getNextPos() {
            return pos + unitSpeed;
        }

        public void move(Double moveLen) {
            if (moveLen == null)
                moveLen = unitSpeed;
            if (pos == 100)
                pos = 0;
            if (moveLen + pos > barLen) {
                fightEventQueue.add(new FightEvent(this, moveLen + pos - barLen, fightList));
                pos = barLen;
            } else
                pos += moveLen;
        }

        public void fight(List<FightMoveControl> fightObjList) {
            //攻击
            System.out.println(name + "，速度:" + String.valueOf((int) (unitSpeed * speedUnit)) + ":开始攻击！");
        }
    }

    public static abstract class GameEvent {
        protected List<FightMoveControl> fightList;

        public GameEvent(List<FightMoveControl> fightList) {
            this.fightList = fightList;
        }

        public abstract void trigger();
    }

    public static class MoveEvent extends GameEvent {
        FightMoveControl fightObj;

        public MoveEvent(FightMoveControl fO, List<FightMoveControl> fightList) {
            super(fightList);
            this.fightObj = fO;
        }

        @Override
        public void trigger() {
            this.fightObj.move(null);
            moveEventQueue.add(new MoveEvent(fightObj, fightList));
           // System.out.println(fightObj.name + "，速度:" + String.valueOf((int) (fightObj.unitSpeed * fightObj.speedUnit)) + ":移动位置:" + fightObj.pos);
        }
    }

    public static class FightEvent extends GameEvent {
        FightMoveControl fightObj;
        double pos;

        public FightEvent(FightMoveControl fO, double pos, List<FightMoveControl> fightList) {
            super(fightList);
            this.fightObj = fO;
            this.pos = pos;
        }

        public void setFightObj(FightMoveControl fightObj) {
            this.fightObj = fightObj;
        }

        public FightMoveControl getFightObj() {
            return fightObj;
        }

        public void setPos(double pos) {
            this.pos = pos;
        }

        public double getPos() {
            return pos;
        }

        @Override
        public void trigger() {
            this.fightObj.fight(fightList);
            this.fightObj.move(pos);
        }
    }

    public static class ShanTu extends FightMoveControl {
        public ShanTu(int speed, String name) {
            super(speed, name);
        }

        @Override
        public void fight(List<FightMoveControl> fightObjList) {
            super.fight(fightObjList);
            moveBar(fightObjList);//释放技能,拉条
        }

        /**
         * 技能释放移动进度条
         */
        public FightEvent moveBar(List<FightMoveControl> fightObjList) {
            int rate = 30;
            for (FightMoveControl actionObj : fightObjList) {
                if (actionObj != this && actionObj.pos != 100 && actionObj instanceof ShanTu) {
                    double moveLen = (actionObj.unitSpeed / this.unitSpeed) * (rate / (barLen * 1.0)) * barLen;
                    actionObj.move(moveLen);
                }
            }

            this.move((rate / (barLen * 1.0)) * barLen);

            return null;
        }
    }
}
